#pragma once
#include <time.h>
#include <functional>
#include <iostream>
#include <cstdlib> // 用于 rand() 和 srand()
#include <ctime>   // 用于 time()

#include <signal.h>
#include <netinet/in.h>

#define MAX_SIZE 1024
#define TIME_WHEEL_NUM 60
#define TIME_WHEEL_TS 1

struct util_timer;
// using task_t = std::function<void()>;
struct User_Data
{
    User_Data()
    {
        sockfd = -1;
        timer = nullptr;
    }
    int getsockfd()
    {
        return sockfd;
    }
    void setaddr(sockaddr_in addr1)
    {
        std::cout << "setaddr(sockaddr_in addr1)" << std::endl;
        addr = addr1;
        std::cout << "setaddr(sockaddr_in addr1)" << std::endl;
    }
    int sockfd;
    sockaddr_in addr;
    std::string buffer;
    util_timer *timer;
};

using func_t = std::function<void(User_Data *)>;
// 最终在User_Data[]中，下标和sockfd对应，User_Data[sockfd]就可以获得sockfd对应的用户信息

// 管理一个用户连接状态的数据结构

// 定时器对象
struct util_timer // 由于最后调用回调函数时，需要关闭sockfd，所以要有一个User_Data的指针
{
    time_t time; // 到期时间

    func_t handler;    // 到达定时的回调函数，close sockfd
    User_Data *client; // 回指用户指针
    util_timer *prev;
    util_timer *next;
};

class util_timer_list
{
public:
    util_timer_list()
    {
    }
    ~util_timer_list()
    {
        // 清理当前链表上的所有节点
        util_timer *tmp = head;
        while (tmp)
        {
            if (head == tail) // 说明只剩一个节点
            {
                delete tmp;
                break;
            }
            else if (head != tail)
            {
                head = head->next;
                head->prev = nullptr;
                delete tmp;
                tmp = head;
            }
        }
    }

    void add_util_timer(util_timer *timer)
    {
        // 用于增加一个timer节点
        // util_timer *tmp = head;
        if (!timer)
        {
            return;
        }
        if (!head)
        {
            head = tail = timer;
            return;
        }

        //  timer  head   tail
        if (timer->time < head->time) // 此时将定时器节点插入到链表首部
        {
            head->prev = timer;
            timer->next = head;
            head = timer;
            return;
        }
        // 此时说明上述情况都不满足，调用重载函数
        add_util_timer(timer, head);
    }

    void adjust_util_timer(util_timer *timer) // 用于需要增加定时时间，调整定时器对象在链表中的位置时
    {
        // 直接将定时器取出重新进行插入
        // 只考虑头节点和非头节点的情况
        // util_timer* prev = head;
        if (!timer)
        {
            return;
        }
        util_timer *tmp = timer->next;

        // 1.如果timer在尾部或者timer不需要调整位置
        if (timer == tail || timer->time < tmp->time)
        {
            return;
        }
        // 2.如果timer在头部时，且需要调整位置，取出&&调整结构再插入
        else if (timer == head)
        {
            head = head->next;
            head->prev = nullptr;
            timer->next = nullptr;
            add_util_timer(timer);
        }
        // 3.如果timer不在头部且需要调整位置时
        else
        {
            tmp->prev = timer->prev;
            timer->prev->next = tmp;
            timer->prev = nullptr;
            timer->next = nullptr;
            add_util_timer(timer);
        }
        return;
    }

    void del_util_timer(util_timer *timer)
    {
        // 删除定时器节点
        if (!timer)
        {
            return;
        }
        /// 如果只有一个定时器
        if (timer == head && head == tail)
        {
            delete timer;
            head = nullptr;
            tail = nullptr;
            return;
        }
        util_timer *tmp = timer->next;
        if (timer == head)
        {
            head = head->next;
            head->prev = nullptr;
            delete timer;
        }
        if (timer == tail)
        {
            tail = timer->prev;
            tail->next = nullptr;
            delete timer;
        }
        timer->prev->next = tmp;
        tmp->prev = timer->prev;
        delete timer;
        return;
    }

    void tick() // 用于给服务器提供的收到 alarm信号 主程序层面提供的对于信号的信号处理函数(在原程序中执行，不去进行信号中断)，调用的定时处理任务
    {
        //
        time_t cur = time(NULL); // 获得当前时间
        util_timer *tmp = head;
        if (!tmp)
        {
            return;
        }
        while (tmp)
        {
            // 直到找到比cur大的时间，退出循环
            if (tmp->time > cur)
            {
                break;
            }
            else
            {
                tmp->handler(tmp->client);
                head = head->next;
                if (head) // head不为空
                {
                    head->prev = nullptr;
                }
                delete tmp;
                tmp = head;
            }
        }
        return;
    }

private:
    void add_util_timer(util_timer *timer, util_timer *list_head) // 重载函数，用于当插入的定时器节点不是绝对时间最小的情况
    {
        if (!timer || !list_head)
        {
            return;
        }
        util_timer *prev = list_head;
        util_timer *tmp = prev->next;
        while (tmp) // 当tmp不为空指针时可以一直查找，直到遇到比timer小的定时器节点
        {
            //  tmp head tail
            if (timer->time < tmp->time)
            {
                prev->next = timer;
                tmp->prev = timer;
                timer->prev = prev;
                timer->next = tmp;
                break;
            }
            prev = tmp;
            tmp = tmp->next;
        }
        // 此时说明要插入到最后一个节点了
        if (!tmp)
        {
            prev->next = timer;
            timer->prev = prev;
            timer->next = nullptr;
            tail = timer;
        }
        return;
    }

    util_timer *head; // 指向头节点的指针
    util_timer *tail; // 指向尾部节点的指针
};
